package com.jxl.helper;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;

import jxl.Sheet;
import jxl.Workbook;

/**
 * 描述：<br>
 * 用於轉換EXCEL數據生成VO模版
 * 
 * @author LazyBear
 * @data 2014-3-31
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public final class JxlHelper {

	/**
	 * 
	 * @author LazyBear 描述:<br>
	 *         將excel文件轉換成JAVABEAN對象 excel文件中，一個sheet代表一個VO
	 *         所有VO以鍵值的方式存入Map集合(類名為鍵,值為此類模版產生的對象集合)
	 * @param <T>
	 * @param filePath
	 * @return
	 */
	public static Map<String, List> excel2Vo(String filePath) {
		Map<String, List> vo_map = new HashMap<String, List>();
		try {
			Workbook workbook = Workbook.getWorkbook(new File(System.getProperty("user.dir") + filePath));
			String[] sheetNames = workbook.getSheetNames();
			for (String className : sheetNames) {
				List objs = new ArrayList<Object>();
				Class<?> clazz = Class.forName(className);
				Sheet sheet = workbook.getSheet(className);
				int rownum = sheet.getRows();
				Field[] fields = FieldUtils.getAllFields(clazz);
				String content;
				for (int i = 1; i < rownum; i++) {
					Object obj = clazz.newInstance();
					Field field;
					for (int j = 0; j < fields.length; j++) {
						field = fields[j];
						content = sheet.getCell(j, i).getContents();
						str2FieldVoluation(obj, field, content);
					}
					objs.add(obj);
				}
				if (objs.size() < 1)
					throw new Exception("this data module don't have data");
				vo_map.put(className, objs);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		if (vo_map.size() < 1)
			return null;
		return vo_map;
	}

	/**
	 * 
	 * @author LazyBear 描述:<br>
	 *         給此屬性賦值,如果屬性為數組,則從value字符串中以","分割數據並組織數據
	 * @param field
	 * @param value
	 */
	private static void str2FieldVoluation(Object tarObj, Field field, String value) {
		Class<?> clazz = field.getType();
		try {

			if (clazz.isArray()) {
				String[] values = StringUtils.split(value, ",");
				Object arrayObj = Array.newInstance(clazz.getComponentType(), values.length);
				setFieldValue(arrayObj, values, clazz.getComponentType().toString());
				FieldUtils.writeDeclaredField(tarObj, field.getName(), arrayObj, true);
			} else {
				FieldUtils.writeDeclaredField(tarObj, field.getName(), setFieldValue(value, clazz.getName()), true);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @author LazyBear 描述:<br>
	 *         給屬性動態賦值
	 * @param valueObj
	 * @param value
	 * @param componentType
	 */
	private static Object setFieldValue(String value, String componentType) {
		Object valueObj = null;
		switch (componentType) {
		case "java.lang.String":
			valueObj = value;
			return valueObj;
		case "int":
			valueObj = Integer.valueOf(value);
			return valueObj;
		case "byte":
			valueObj = Byte.valueOf(value);
			return valueObj;
		case "short":
			valueObj = Short.valueOf(value);
			return valueObj;
		case "long":
			valueObj = Long.valueOf(value);
			return valueObj;
		case "float":
			valueObj = Float.valueOf(value);
			return valueObj;
		case "double":
			valueObj = Double.valueOf(value);
			return valueObj;
		case "boolean":
			valueObj = Boolean.valueOf(value);
			return valueObj;
		}
		return null;
	}

	/**
	 * @author LazyBear 描述:<br>
	 *         給屬性動態賦值(數組)
	 * @param arrayObj
	 * @param vaules
	 * @param componentType
	 */
	private static void setFieldValue(Object arrayObj, String[] vaules, String componentType) {
		switch (componentType) {
		case "java.lang.String":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, vaules[i]);
			}
			break;
		case "int":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, Integer.valueOf(vaules[i]));
			}
			break;
		case "byte":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, Byte.valueOf(vaules[i]));
			}
			break;
		case "short":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, Short.valueOf(vaules[i]));
			}
			break;
		case "long":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, Long.valueOf(vaules[i]));
			}
			break;
		case "float":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, Float.valueOf(vaules[i]));
			}
			break;
		case "double":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, Double.valueOf(vaules[i]));
			}
			break;
		case "boolean":
			for (int i = 0; i < vaules.length; i++) {
				Array.set(arrayObj, i, Boolean.valueOf(vaules[i]));
			}
			break;
		}
	}
}
